from django.core.paginator import Paginator, EmptyPage
from django.http import JsonResponse
from django.shortcuts import render

# Create your views here.
from django.views import View
from haystack.views import SearchView
from apps.contents.models import GoodsCategory
from apps.goods.models import SKU
from apps.goods.utils import get_breadcrumb


class ListView(View):
    """商品列表页
    GET  /list/(?P<category_id>\d+)/skus/
    """

    def get(self, request, category_id):
        """
        提供商品列表页和面包屑导航
        :param request:
        :param category_id: 商品第三级分类
        :return: JSON
        """
        # 接收参数
        page_num = request.GET.get('page')  # 当前用户想看的页码
        page_size = request.GET.get('page_size')    # 该页中想看的记录的个数
        ordering = request.GET.get('ordering')  # 排序字段

        # 校验参数
        # 校验category_id是否存在
        try:
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            return JsonResponse({
                'code': 400,
                'errmsg': 'category_id不存在'
            })
        # 提示:page_num,page_size,ordering不需要单独校验,因为再排序和分页时校验的

        # 实现核心逻辑:排序和分页,面包屑导航
        # 我们需要是查询指定分类下,未被下架的sku信息,在排序
        # 没有找到数据,返回 空列表
        skus = SKU.objects.filter(category=category, is_launched=True).order_by(ordering)

        # 分页查询
        # loader 加载器(首页静态化使用到了)  Paginator 分页器
        # 创建分页器对象
        # 分页器对象 = Paginator(要分页的查询集, 每页记录个数)
        paginator = Paginator(skus, page_size)

        # 获取指定页中的模型数据: paginator.page(页码)
        # 为防止页码越界异常捕获
        try:
            page_skus = paginator.page(page_num)
        except EmptyPage:
            return JsonResponse({
                'code': 400,
                'errmsg': '页码错误'
            })

        # 面包屑导航封装成工具方法
        # category_id
        breadcrumb = get_breadcrumb(category)

        # 获取分页后的总页数 = 分页器对象.num_pages
        total_pages = paginator.num_pages

        # 将分页后的查询集转列表
        list = []
        for sku in page_skus:
            list.append({
                'id': sku.id,
                'default_image_url': sku.default_image.url,
                'name': sku.name,
                'price': sku.price
            })

        # 响应结果
        return JsonResponse({
            'code': 0,
            'errmsg': 'ok',
            'breadcrumb': breadcrumb, # 面包屑导航
            'list': list,     # 排序后的分页数据,不能是模型数据,因为JsonResponse不识别
            'count': total_pages,    # 分页后的总页数
        })


class HotGoodsView(View):
    """商品列表页热销排行
    GET /hot/(?P<category_id>\d+)/
    """

    def get(self, request, category_id):
        """
        提供商品热销排行
        :param request:
        :param category_id: 第三级分类
        :return: JSON
        """
        # 校验category_id是否存在
        try:
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            return JsonResponse({
                'code': 400,
                'errmsg': 'category_id不存在'
            })

        # 查询指定分类下,未被下架的销量最好的前两款商品
        # 按照销量倒序(销量越高越靠前) order_by('-sales')
        skus = SKU.objects.filter(category=category, is_launched=True).order_by('-sales')[:2]
        # # 根据销量倒序
        # try:
        #     skus = SKU.objects.filter(category_id=category_id,
        #                               is_launched=True).order_by('-sales')[:2]
        # except Exception as e:
        #     return JsonResponse({'code': 400,
        #                          'errmsg': '获取商品出错'})

        # 将查询集转字典列表
        hot_skus = []
        for sku in skus:
            hot_skus.append({
                'id': sku.id,
                'default_image_url': sku.default_image.url,
                'name': sku.name,
                'price': sku.price
            })

        # 响应结果
        return JsonResponse({
            'code': 0,
            'errmsg': 'ok',
            'hot_skus': hot_skus
        })


class MySearchView(SearchView):
    """自定义商品搜索视图
    目的:重写SearchView类中的create_response()方法,并返回检索后的json数据
    GET /search/
    """

    def create_response(self):
        """返回检索后的json数据"""
        # 根据前端传入的page_size进行反页,如果不指定进行全局设置,反之局部设置
        # self.results_per_page = int(self.request.GET.get('page_size'))
        # self.results_per_page = 5

        # 获取搜索结果,并且分好页了
        context = self.get_context()

        # 获取检索到的模型数据
        skus = context['page'].object_list
        # SearchResult 类型,对象列表

        # 遍历skus,取出检索到的sku,转为字典列表
        data_list = []
        for sku in skus:
            data_list.append({
                'id': sku.object.id,
                'name': sku.object.name,
                'price': sku.object.price,
                'default_image_url': sku.object.default_image.url,
                'searchkey': context.get('query'),
                'page_size': context['page'].paginator.num_pages,   # 分页后的总页数,为了让前端显示相同数量的(分页查看)按钮
                'count': context['page'].paginator.count
            })

        # 将检索到的数据转json返回
        return JsonResponse(data_list, safe=False)
